package com.szholly.data.general;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.szholly.utils.spring.SpringBeanFactory;
import com.szholly.utils.util.StringUtils;
import com.szholly.data.cache.MetadataDataCache;
import com.szholly.data.general.metadata.table.*;

/**
 * 定义基于数据库配置的ITable实现
 */
@Component("TableClass")
@Scope("prototype")
public class TableClass extends InterceptorTableBase {

	/**
	 * 元数据表名称
	 */
	private String medataTableName;
	/**
	 * 元数据别名
	 */
	private String medataTableAliasName;
	/**
	 * 表分组名称
	 */
	private String tableGroupName;
	/**
	 * 真实表名称
	 */
	private String tableName;
	/**
	 * 是否是代码表
	 */
	private boolean isCodeTable;
	/**
	 * 是否是树型表
	 */
	private boolean isTreeTable;
	/**
	 * 字典表的ID字段名称
	 */
	private String idFieldName = "";
	/**
	 * 字典表的PID字段名称
	 */
	private String pidFieldName = "";
	/**
	 * 字典表的Code字段名称
	 */
	private String codeFieldName = "";
	/**
	 * 字典表的Caption字段名称
	 */
	private String captionFieldName = "";
	/**
	 * 字典表的排序字段名称
	 */
	private String orderFieldName = "";
	/**
	 * 字典表的是否使用字段名称
	 */
	private String isUserFieldName = "";
	/**
	 * 字典表的是否可编辑字段名称
	 */
	private String isEditFieldName = "";
	/**
	 * 字典表的级别字段名称
	 */
	private String leverFieldName = "";
	/**
	 * 字典表的域名称字段名称
	 */
	private String domainFieldName = "";
	/**
	 * 表类型
	 */
	private TableType tableType;
	/**
	 * 空间信息
	 */
	private String spaceInfo;
	/**
	 * 如果是代码表，是否按代码表管理
	 */
	private boolean canManage;
	/**
	 * 关系节点
	 */
	private RelationNode relationNode;
	/**
	 * GUID字段名称
	 */
	private String guidFieldName;
	/**
	 * 版本字段名称
	 */
	private String versionFieldName;
	/**
	 * 系统名称字段名称
	 */
	private String companyName;
	/**
	 * 字段列表
	 */
	private HashMap<String, Field> fieldList = new HashMap<String, Field>();
	/**
	 * 初始化注册表
	 */
	private RowBase regRow = null;
	/**
	 * 初始化连接表
	 */
	private RowBase connectionRow = null;

	public TableClass(String medataTableName) {
		this.medataTableName = medataTableName;

		InitMedata();
	}

	private void InitMedata() {
		// 结构表信息
		List<RowBase> list = MetadataDataCache.getTablesRowsCache();
		RowBase tablesRow = null;
		for (RowBase item : list) {
			String tableID = (String) item.getValue(GlobalDataType.String,
					TablesRow.FIELD_TABLEID);
			if (tableID.equals(medataTableName)) {
				tablesRow = item;
				break;
			}
		}
		if (tablesRow == null) {
			throw new RuntimeException("未能找到结构表:" + medataTableName);
		}

		this.spaceInfo = (String) tablesRow.getValue(GlobalDataType.String,
				TablesRow.FIELD_SPATIALREFERENCE);
		String strCanManage = (String) tablesRow.getValue(
				GlobalDataType.String, TablesRow.FIELD_MANAGERCODETABLE);
		this.canManage = true;
		if (!StringUtils.IsNullOrSpace(strCanManage)) {
			this.canManage = (Boolean) tablesRow.getValue(
					GlobalDataType.Boolean, TablesRow.FIELD_MANAGERCODETABLE);
		}
		this.medataTableAliasName = (String) tablesRow.getValue(
				GlobalDataType.String, TablesRow.FIELD_TABLEALIASNAME);
		this.tableGroupName = (String) tablesRow.getValue(
				GlobalDataType.String, TablesRow.FIELD_TABLEGROUP);
		this.tableType = TableType.getTableTypeByTypeId((Integer) tablesRow
				.getValue(GlobalDataType.Int32, TablesRow.FIELD_TABLETYPE));

		String treeTableField = (String) tablesRow.getValue(
				GlobalDataType.String, TablesRow.FIELD_TREETABLEFIELD);
		isCodeTable = false;
		isTreeTable = false;
		if (!StringUtils.IsNullOrSpace(treeTableField)) {
			String[] msg = treeTableField.split(",");
			if (msg.length < 4){
				throw new RuntimeException("树型表配置错误，在表：" + medataTableName
						+ "中");
			}

			idFieldName = msg[0];
			pidFieldName = msg[1];

			if (!StringUtils.IsNullOrSpace(idFieldName)
					&& !StringUtils.IsNullOrSpace(pidFieldName)) {
				isTreeTable = true;
			}else{
				isCodeTable = true;
			}

			codeFieldName = msg[2];
			captionFieldName = msg[3];
			if (msg.length >= 5)
				leverFieldName = msg[4];
			if (msg.length >= 6)
				isUserFieldName = msg[5];
			if (msg.length >= 7)
				isEditFieldName = msg[6];
			if (msg.length >= 8)
				orderFieldName = msg[7];
			if (msg.length >= 9)
				domainFieldName = msg[8];
		}
		
		String sysFields = (String) tablesRow.getValue(
				GlobalDataType.String, TablesRow.FIELD_SYSFIELDS);
		if (!StringUtils.IsNullOrSpace(sysFields)) {
			String[] msg = sysFields.split(",");
			if (msg.length != 3)
				throw new RuntimeException("系统字段名称配置错误，在表：" + medataTableName + "中");
			guidFieldName = msg[0];
			versionFieldName = msg[1];
			companyName=msg[2];
		}else{
			guidFieldName = RowBase.FIELD_GUID;
			versionFieldName = RowBase.FIELD_VERSION;
			companyName=RowBase.FIELD_COMPANY;
		}

		// 表字段信息
		list = MetadataDataCache.getTableMetadataRowsCache();
		List<RowBase> fieldRows = new ArrayList<RowBase>();
		for (RowBase item : list) {
			String tableID = (String) item.getValue(GlobalDataType.String,
					TableMetadataRow.FIELD_TABLEID);
			if (tableID.equals(medataTableName)) {
				fieldRows.add(item);
			}
		}

		NetDataTypeConvert dataTypeConvert = new NetDataTypeConvert();

		if (fieldRows != null && fieldRows.size() > 0) {
			for (RowBase row : fieldRows) {
				String fieldName = (String) row.getValue(GlobalDataType.String,
						TableMetadataRow.FIELD_FIELDNAME);
				if (row == null || StringUtils.IsNullOrSpace(fieldName))
					continue;

				fieldName = fieldName.toUpperCase().trim();
				if (fieldList.containsKey(fieldName))
					throw new RuntimeException("记录重复！");

				Field field = new Field();
				field.setAllowNull((Boolean) row.getValue(
						GlobalDataType.Boolean,
						TableMetadataRow.FIELD_ALLOWNULL));
				field.setCanShow((Boolean) row.getValue(GlobalDataType.Boolean,
						TableMetadataRow.FIELD_CANSHOW));
				field.setCodeRule((String) row.getValue(GlobalDataType.String,
						TableMetadataRow.FIELD_CODERULE));
				field.setCodeRuleExp((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_CODERULEEXP));
				field.setCodeTablePK((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_CODETABLEPK));
				field.setCodeDomainName((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_CODETABLEWHERE));
				field.setCodeGetScript((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_CODEGETSCRIPT));
				field.setCodeSetScript((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_CODESETSCRIPT));
				field.setControlType((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_CONTROLTYPE));
				field.setDataType(dataTypeConvert.Convert((String) row
						.getValue(GlobalDataType.String,
								TableMetadataRow.FIELD_DATATYPE)));
				field.setDecimaldigits((Integer) row.getValue(GlobalDataType.Int32,
						TableMetadataRow.FIELD_DECIMALDIGITS));
				field.setDefaultValue((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_DEFAULTVALUE));
				field.setFieldAliasName((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_FIELDALIASNAME));
				field.setFieldID((Integer) row.getValue(GlobalDataType.Int32,
						TableMetadataRow.FIELD_FIELDID));
				field.setFieldName((String) row.getValue(GlobalDataType.String,
						TableMetadataRow.FIELD_FIELDNAME));
				field.setGroup((String) row.getValue(GlobalDataType.String,
						TableMetadataRow.FIELD_GROUP));
				field.setIsAuto((Boolean) row.getValue(GlobalDataType.Boolean,
						TableMetadataRow.FIELD_ISAUTO));
				field.setIsCrucial((Boolean) row.getValue(
						GlobalDataType.Boolean,
						TableMetadataRow.FIELD_ISCRUCIAL));
				field.setIsEssential((Boolean) row.getValue(
						GlobalDataType.Boolean,
						TableMetadataRow.FIELD_ISESSENTIAL));
				field.setIsKey((Boolean) row.getValue(GlobalDataType.Boolean,
						TableMetadataRow.FIELD_ISKEY));
				field.setMaxLen((Integer) row.getValue(GlobalDataType.Int32,
						TableMetadataRow.FIELD_MAXLEN));
				field.setReadOnly((Boolean) row
						.getValue(GlobalDataType.Boolean,
								TableMetadataRow.FIELD_READONLY));
				field.setRelationGroup((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_RELATIONGROUP));
				field.setRelationIndex((Integer) row.getValue(GlobalDataType.Int32,
						TableMetadataRow.FIELD_RELATIONINDEX));
				field.setUniqueGroup((String) row.getValue(
						GlobalDataType.String,
						TableMetadataRow.FIELD_UNIQUEGROUP));
				field.setUnit((String) row.getValue(GlobalDataType.String,
						TableMetadataRow.FIELD_UNIT));
				field.setControlWidth((Integer) row.getValue(GlobalDataType.Int32,
						TableMetadataRow.FIELD_CONTROLWIDTH));

				fieldList.put(fieldName, field);
			}
		}

		RelationMap relationMap = MetadataDataCache.getRelationMapCache();
		this.relationNode = relationMap.GetNode(this.medataTableName);

		// 找注册表
		list = MetadataDataCache.getTableRegRowsCache();
		for (RowBase item : list) {
			String tableID = (String) item.getValue(GlobalDataType.String,
					DataRegRow.FIELD_TABLEID);
			if (tableID.equals(medataTableName)) {
				regRow = item;
				break;
			}
		}

		if (regRow != null) {
			this.tableName = (String) regRow.getValue(GlobalDataType.String,
					DataRegRow.FIELD_TABLENAME);
			// 连接表
			String connectionID = (String) regRow.getValue(
					GlobalDataType.String, DataRegRow.FIELD_CONNECTIONID);
			list = MetadataDataCache.getConnectionTableRowsCache();

			for (RowBase item : list) {
				String conID = (String) item.getValue(GlobalDataType.String,
						ConnectionRow.FIELD_CONNECTIONID);
				if (conID.equals(connectionID)) {
					connectionRow = item;
					break;
				}
			}
		} else {
			this.tableName = this.medataTableName;
		}
	}

	@Override
	public String getMetadataTableName() {
		return medataTableName;
	}

	/**
	 * 获取表名称
	 */
	@Override
	public String getTableName() {
		return this.tableName;
	}

	@Override
	public String getMetadataTableAliasName() {
		return this.medataTableAliasName;
	}

	@Override
	protected HashMap<String, Field> fields() {
		return fieldList;
	}

	@Override
	public String getTableGroup() {
		return this.tableGroupName;
	}

	/**
	 * 获取表类型
	 */
	@Override
	public TableType getTableType() {
		return this.tableType;
	}

	/**
	 * 是否是代码表
	 */
	public boolean getIsCodeTable() {
		return this.isCodeTable;
	}

	/**
	 * 是否为树型表
	 */
	public boolean getIsTreeTable() {
		return this.isTreeTable;
	}

	/**
	 * 获取或设置数据字典表代码字段名
	 */
	public String getCodeFieldName() {
		return this.codeFieldName;
	}

	/**
	 * 获取或设置数据字典表值字段名
	 */
	public String getCaptionFieldName() {
		return this.captionFieldName;
	}

	/**
	 * 获取或设置树形表ID字段名
	 */
	public String getIDFieldName() {
		return this.idFieldName;
	}

	/**
	 * 获取或设置树形表PID字段名
	 */
	public String getPIDFieldName() {
		return this.pidFieldName;
	}

	/**
	 * 表关系
	 */
	public RelationNode getRelation() {
		return relationNode;
	}

	/**
	 * 空间参考信息
	 */
	public String getSpatialReference() {
		return spaceInfo;
	}

	/**
	 * 获取是否管理的代码表
	 */
	public boolean getIsManageCodeTable() {
		return this.canManage;
	}

	/**
	 * 获取排序字段名
	 */
	public String getOrderFieldName() {
		return this.orderFieldName;
	}

	/**
	 * 获取是否使用字段名
	 */
	public String getIsUsedFieldName() {
		return this.isUserFieldName;
	}

	/**
	 * 获取是否可编辑字段名
	 */
	public String getIsEditFieldName() {
		return this.isEditFieldName;
	}

	/**
	 * 获取级别字段名
	 */
	public String getLevelFieldName() {
		return this.leverFieldName;
	}

	/**
	 * 获取字典阈名称
	 */
	public String getDomainFieldName() {
		return this.domainFieldName;
	}
	
	@Override
	public String getGUIDFieldName() {
		return this.guidFieldName;
	}

	@Override
	public String getVersionFieldName() {
		return this.versionFieldName;
	}

	@Override
	public String getCompanyName() {
		return this.companyName;
	}

	/**
	 * @Title: getWorkspace
	 * @Description: 获取当前表空间
	 * @param @return
	 * @return IWorkspace 返回类型
	 * @throws
	 */
	public IWorkspace getWorkspace() {
		// 没有注册，或连接信息表，表默认表空间中处理
		if (regRow == null || connectionRow == null) {
			return getWorkspaceEx();
		}

		// 第三步，创建数据库连接
		String conStr = (String) connectionRow.getValue(GlobalDataType.String,
				ConnectionRow.FIELD_CONNECTIONSTR);
		ConnectionInfo conInfo = new ConnectionInfo(conStr, "");
		int workspaceTypeId = Integer.parseInt(connectionRow.getValue(GlobalDataType.String, 
				ConnectionRow.FIELD_DATABASETYPE).toString());
		conInfo.setWorkspaceType(WorkspaceType
				.getWorkspaceTypeByTypeId(workspaceTypeId));
		IWorkspaceFactory workspaceFactory = (IWorkspaceFactory) SpringBeanFactory
				.getBean("WorkspaceFactory");
		IWorkspace pWorkspace = workspaceFactory.openDbWorkspace(conInfo);
		tableInit(pWorkspace);
		return pWorkspace;
	}

	private IWorkspace getWorkspaceEx() {
		IWorkspaceFactory workspaceFactory = (IWorkspaceFactory) SpringBeanFactory
				.getBean("WorkspaceFactory");
		IWorkspace pWorkspace = workspaceFactory.openWorkspace();
		tableInit(pWorkspace);
		return pWorkspace;
	}

	private boolean tableIsInit = false;

	private void tableInit(IWorkspace pWorkspace) {
		if (tableIsInit) {
			return;
		}
		if (!pWorkspace.objectExist(this.getTableName())) {
			pWorkspace.createTable(this, getTableName());
		}
		tableIsInit = true;
	}
}
